﻿using AutoMapper;
using System;
using Local = Sustainalytics.Entities.RiskRatings;
using Shared = Sustainalytics.SharedEntities.RiskRatingsResearch;

namespace Sustainalytics.ClientDW.Synchronization.SyncRiskRatingsData
{
    public static class AutoMapperConfig
    {
        public static void RegisterMappings()
        {
            Mapper.Reset();
            Mapper.Initialize(Config);
        }

        private static void Config(IMapperConfigurationExpression cfg)
        {
            cfg.CreateMissingTypeMaps = true;
            cfg.AllowNullCollections = true;
            cfg.AllowNullDestinationValues = true;

            cfg.CreateMap<Shared.RiskRatingResearchProfile, Local.RiskRatingResearchProfileBase>()
                .IncludeAllDerived()
                .ForMember(x => x.PeerGroup, x => x.Ignore())
                .ForMember(x => x.SubPeerGroup, x => x.Ignore())
                .ForMember(x => x.SubPeerGroupId, x => x.Ignore())
                .ForMember(x => x.Country, x => x.Ignore())
                .ForMember(x => x.Exchange, x => x.Ignore())
                .ForMember(x => x.Ticker, x => x.Ignore())
                .ForMember(x => x.ExchangeTicker, x => x.Ignore())
                .ForMember(x => x.MarketCapitalization, x => x.Ignore())
                .ForMember(x => x.Cluster, x => x.MapFrom(y => y.Cluster.Value))
                .ForMember(x => x.Assessment, x => x.MapFrom(y => y.Cluster.Bind(c => c.Assessment)))
                .ForMember(x => x.ExposureCluster, x => x.MapFrom(y => y.ExposureCluster.Bind(c => c.Assessment)))
                .ForMember(x => x.ManagementCluster, x => x.MapFrom(y => y.ManagementCluster.Bind(c => c.Assessment)))
                .ForMember(x => x.ManageableCluster, x => x.MapFrom(y => y.ManageableCluster.Bind(c => c.Assessment)))
                .ForMember(x => x.OverallExcessExposure, x => x.MapFrom(y => y.ManagementRisk.Exposure.Value - y.SubIndustryExposureScore.Value));
            cfg.CreateMap<Shared.ComprehensiveRiskRatingResearchProfile, Local.RiskRatingResearchProfile>();
            cfg.CreateMap<Shared.CoreRiskRatingResearchProfile, Local.CoreRiskRatingResearchProfile>();

            cfg.CreateMap<Shared.MaterialEsgIssue, Local.RiskRatingMaterialEsgIssueBase>()
                .IncludeAllDerived()
                .ForMember(x => x.Type, x => x.MapFrom(y => y.Type.Value))
                .ForMember(x => x.TypeTimestamp, x => x.MapFrom(y => y.Type.Timestamp))
                .ForMember(x => x.Cluster, x => x.MapFrom(y => y.Cluster.Value))
                .ForMember(x => x.Assessment, x => x.MapFrom(y => y.Cluster.Bind(c => c.Assessment)))
                .ForMember(x => x.ExposureCluster, x => x.MapFrom(y => y.ExposureCluster.Bind(c => c.Assessment)))
                .ForMember(x => x.ManagementCluster, x => x.MapFrom(y => y.ManagementCluster.Bind(c => c.Assessment)))
                .ForMember(x => x.ManageableCluster, x => x.MapFrom(y => y.ManageableCluster.Bind(c => c.Assessment)))
                .ForMember(x => x.ExcessExposure, x => x.MapFrom(y => y.ManagementRisk.Exposure.Value - y.SubIndustryExposureScore.Value));
            cfg.CreateMap<Shared.MaterialEsgIssue, Local.RiskRatingMaterialEsgIssue>()
                .ForMember(x => x.Id, x => x.MapFrom(y => Guid.NewGuid()))
                .ForMember(x => x.CompanyId, x => x.Ignore())
                .ForMember(x => x.CapitalIqId, x => x.Ignore())
                .ForMember(x => x.SubPeerGroup, x => x.Ignore())
                .ForMember(x => x.SubPeerGroupId, x => x.Ignore())
                .ForMember(x => x.PeerGroup, x => x.Ignore())
                .ForMember(x => x.CompanyName, x => x.Ignore());

            cfg.CreateMap<Shared.RiskRatingClusterBase, Local.RiskRatingClusterBase>()
                .IncludeAllDerived()
                .ForMember(x => x.UpperBound, x => x.MapFrom(bound => Math.Round(bound.UpperBound, 0)))
                .ForMember(x => x.LowerBound, x => x.MapFrom(bound => Math.Round(bound.LowerBound, 0)))
                .ForMember(x => x.Id, x => x.MapFrom(y => Guid.NewGuid()));
            cfg.CreateMap<Shared.RiskRatingCluster, Local.RiskRatingCluster>();
            cfg.CreateMap<Shared.ManagementCluster, Local.ManagementCluster>();
            cfg.CreateMap<Shared.ManageableCluster, Local.ManageableCluster>();
            cfg.CreateMap<Shared.ExposureCluster, Local.ExposureCluster>();

            cfg.CreateMap<Shared.Indicator, Local.RiskRatingIndicatorBase>()
                .IncludeAllDerived()
                .ForMember(x => x.Id, x => x.MapFrom(y => Guid.NewGuid()))
                .ForMember(x => x.CompanyId, x => x.Ignore())
                .ForMember(x => x.ExternalId, x => x.Ignore());
            cfg.CreateMap<Shared.ComprehensiveIndicator, Local.ComprehensiveRiskRatingIndicator>()
                .ForMember(x => x.MeiExternalId, x => x.Ignore());
            cfg.CreateMap<Shared.CoreIndicator, Local.CoreRiskRatingIndicator>();

            cfg.CreateMap<Shared.ManagementRisk, Local.ManagementRisk>();
            cfg.CreateMap<Shared.CheckBox, Local.CheckBox>();

            cfg.CreateMap(typeof(Shared.Timestamped<>), typeof(Timestamped<>));
        }
    }
}

namespace Sustainalytics
{
    public static class SharedTimestampedExtensions
    {
        public static Shared.Timestamped<U> Bind<T, U>(this Shared.Timestamped<T> timestamped, Func<T, U> func)
        {
            if (timestamped == null || Equals(timestamped.Value, null))
                return null;

            return new Shared.Timestamped<U> { Value = func(timestamped.Value), Timestamp = timestamped.Timestamp };
        }
    }
}
